package com.shop.util;

import com.shop.entity.MySystemInfo;
import org.hyperic.sigar.*;
import org.springframework.util.StringUtils;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.RuntimeMXBean;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.*;

public class MonitorSystemInfo {

    private Sigar sigar;

    private SigarProxy proxy;

    private static final RuntimeMXBean RUNTIME;

    static {
        RUNTIME = ManagementFactory.getRuntimeMXBean();
    }

    public final Map<String, Object> values;

    public MonitorSystemInfo() throws InterruptedException {
        this.values = new LinkedHashMap<>();
//        runtimeInfo();
//        fillHeap(1000);
    }

    protected void runtimeInfo() {
//        List<String> jvmArgs = RUNTIME.getInputArguments();
//        values.put("jvm.args", jvmArgs);
//        String[] jvmSpec = {
//                RUNTIME.getVmVendor(),
//                RUNTIME.getVmName(),
//                RUNTIME.getSystemProperties().get("java.version"),
//                RUNTIME.getVmVersion()
//        };
//        values.put("jvm.spec", jvmSpec);
//        values.put("jvm.classpath", RUNTIME.getClassPath());
    }

    /**
     * JVM内存信息
     */
    public void fillHeap(Integer num) throws InterruptedException {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for(int i=0; i < num; i++){
            // 延时10秒
            Thread.sleep(10000);
            byte[] bt = new byte[512 * 1024];
            MySystemInfo info = memoryInfo();
            if (Integer.parseInt(info.getJvmHeadMaxMemory()) - Integer.parseInt(info.getJvmHeadUsedMemory()) > 50) {
                System.gc();
            }
            System.out.println("当前时间:" + df.format(new Date()) + info);
        }
        // 触发垃圾回收
        System.gc();
    }

    public MySystemInfo memoryInfo(){
        MemoryMXBean memory = ManagementFactory.getMemoryMXBean();
        MemoryUsage headMemory = memory.getHeapMemoryUsage();
//        System.out.println("head堆:");
        MySystemInfo info = new MySystemInfo();
        info.setJvmHeadInitMemory(String.valueOf(headMemory.getInit() / 1024 / 1024));
        info.setJvmHeadMaxMemory(String.valueOf(headMemory.getInit() / 1024 / 1024));
        info.setJvmHeadUsedMemory(String.valueOf(headMemory.getUsed() / 1024 / 1024));
        info.setJvmNonHeapCommittedMemory(String.valueOf(headMemory.getCommitted() / 1024 / 1024));
        info.setJvmHeadRate(headMemory.getUsed() * 100 / headMemory.getCommitted() + "%");

//        values.put("初始(MB)", headMemory.getInit() / 1024 / 1024);
//        values.put("最大(上限)(MB)", headMemory.getMax() / 1024 / 1024);
//        values.put("当前(已使用)(MB)", headMemory.getUsed() / 1024 / 1024);
//        values.put("提交的内存(已申请)(MB)", headMemory.getCommitted() / 1024 / 1024);
//        values.put("使用率", headMemory.getUsed() * 100 / headMemory.getCommitted() + "%");


//        System.out.println("non-head非堆:");
        MemoryUsage nonHeadMemory = memory.getNonHeapMemoryUsage();

        info.setJvmNonHeapInitMemory(String.valueOf(nonHeadMemory.getInit() / 1024 / 1024));
        info.setJvmNonHeapMaxMemory(String.valueOf(nonHeadMemory.getMax() / 1024 / 1024));
        info.setJvmNonHeapUsedMemory(String.valueOf(nonHeadMemory.getUsed() / 1024 / 1024));
        info.setJvmNonHeapCommittedMemory(String.valueOf(nonHeadMemory.getCommitted() / 1024 / 1024));
        info.setJvmNonHeapRate(nonHeadMemory.getUsed() * 100 / nonHeadMemory.getCommitted() + "%");

//        values.put("初始(MB)", nonHeadMemory.getInit() / 1024 / 1024);
//        values.put("最大(上限)(MB)", nonHeadMemory.getMax() / 1024 / 1024);
//        values.put("当前(已使用)(MB)", nonHeadMemory.getUsed() / 1024 / 1024);
//        values.put("提交的内存(已申请)(MB)", nonHeadMemory.getCommitted() / 1024 / 1024);
//        values.put("使用率", nonHeadMemory.getUsed() * 100 / nonHeadMemory.getCommitted() + "%");
        return info;
    }


    private void sigarInit(boolean isProxy) {
        sigar = new Sigar();
        if (isProxy) {
            proxy = SigarProxyCache.newInstance(this.sigar);
        }
    }

    private void shutdown() {
        this.sigar.close();
    }

    /**
     * 获取内存使用率
     */
    public String getMemoryUsageRate() throws SigarException {
        try {
            sigarInit(false);
            Mem mem = sigar.getMem();
            // 获取总内存数
            Long total = mem.getTotal() / 1024L;
            // 获取已使用内存数
            Long used = mem.getUsed() / 1024L;
            // 获取百分比
            Long percentile = total / 100;
            return "内存使用率：" + used / percentile + "%";
        } finally {
            shutdown();
        }
    }

    /**
     * 获取cpu使用率
     */
    public String getCpuUsageRate() throws SigarException {
        try {
            sigarInit(false);
            MySystemInfo info = new MySystemInfo();
            return "CPU的使用率:" + CpuPerc.format(sigar.getCpuPerc().getCombined());
        } finally {
            if (!StringUtils.isEmpty(sigar)) {
                shutdown();
            }
        }
    }

    /**
     * 获取磁盘使用率
     */
    public List<String> getDiskUsageRate() throws Exception {
        List<String> stringList = new ArrayList<>();
        try {
            sigarInit(false);
            FileSystem[] list = sigar.getFileSystemList();
            for (FileSystem fileSystem : list) {
                FileSystemUsage usageRate = sigar.getFileSystemUsage(fileSystem.getDirName());
                double usePercent = usageRate.getUsePercent() * 100D;
                stringList.add(fileSystem.getDevName() + "磁盘的使用率:" + (int) usePercent + "%");
            }
        } finally {
            if (!StringUtils.isEmpty(sigar)) {
                shutdown();
            }
        }
        return stringList;
    }

    /**
     * 获取磁盘IO的使用情况
     */
    public String getDiskIoUsageRate() throws Exception {
        // 当前每秒的读写量
        long tempTotal = getTotalByte();
        Thread.sleep(1000);
        long total = getTotalByte();
        // 字节转成kb
        double cha = (double) (total - tempTotal) / 1024;
        // 转成MB,并保留1位小数
        BigDecimal bigDecimal = new BigDecimal(cha / 1024);
        double value = bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        return "磁盘IO的使用情况：" + value + " MB/S";
    }

    /**
     * 获取磁盘IO的读写数量
     */
    public long getTotalByte() {
        long totalByte = 0;
        try {
            sigarInit(false);
            FileSystem[] list = sigar.getFileSystemList();
            for (FileSystem fileSystem : list) {
                if (fileSystem.getType() == 2) {
                    FileSystemUsage usage = sigar.getFileSystemUsage(fileSystem.getDirName());
                    totalByte += usage.getDiskReadBytes();
                    totalByte += usage.getDiskWriteBytes();
                }
            }
        } catch (SigarException e) {
            e.printStackTrace();
        } finally {
            if (!StringUtils.isEmpty(sigar)) {
                shutdown();
            }
        }
        return totalByte;
    }
    /**
     * 获取磁盘使用情况
     *
     */
    public String path() throws Exception {
        String path = getClass().getResource("/").getFile();
        if (path.contains("/") && path.contains(":")) {
            path = path.replace("/", "").substring(0, path.indexOf(":"));
        }
        for (String disk : this.getDiskUsageRate()) {
            if (disk.contains(path) || disk.contains("root")) {
                return "当前磁盘的使用率：" + disk;
            }
        }
        return "未找到相应的磁盘";
    }


    //获取当前机器的正式域名
    public String getFQDN() {
        try {
            return InetAddress.getLocalHost().getCanonicalHostName();
        } catch (UnknownHostException e) {
            try {
                sigarInit(false);
                return sigar.getFQDN();
            } catch (SigarException ex) {
                return null;
            } finally {
                shutdown();
            }
        }
    }

    // 获取到当前机器的IP地址
    public String getDefaultIpAddress() throws UnknownHostException {
        String address = null;
        try {
            sigarInit(false);
            address = InetAddress.getLocalHost().getHostAddress();
            // 没有出现异常而正常当取到的IP时，如果取到的不是网卡循回地址时就返回
            // 否则再通过Sigar工具包中的方法来获取
            if (!NetFlags.LOOPBACK_ADDRESS.equals(address)) {
                return address;
            }
        } catch (UnknownHostException e) {
            throw new UnknownHostException("hostname not in DNS");
        }

        try {
            address = sigar.getNetInterfaceConfig().getAddress();
        } catch (SigarException e) {
            address = NetFlags.LOOPBACK_ADDRESS;
        } finally {
            shutdown();
        }
        return address;
    }

    // 获取到当前机器的MAC地址
    public String getMAC() {
        try {
            sigarInit(false);
            String[] ifaces = sigar.getNetInterfaceList();
            String hwaddr = null;
            for (String iface : ifaces) {
                NetInterfaceConfig cfg = sigar.getNetInterfaceConfig(iface);
                if (NetFlags.LOOPBACK_ADDRESS.equals(cfg.getAddress()) || (cfg.getFlags() & NetFlags.IFF_LOOPBACK) != 0 || NetFlags.NULL_HWADDR.equals(cfg.getHwaddr())) {
                    continue;
                }
                hwaddr = cfg.getHwaddr();
                break;
            }
            return !StringUtils.isEmpty(hwaddr) ? hwaddr : null;
        } catch (Exception e) {
            return null;
        } finally {
            if (!StringUtils.isEmpty(sigar)) {
                shutdown();
            }
        }
    }
}
